package com.gitee.qdbp.general.common.biz.reusable.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.gitee.qdbp.able.exception.ServiceException;
import com.gitee.qdbp.able.jdbc.ordering.OrderPaging;
import com.gitee.qdbp.able.jdbc.paging.PageList;
import com.gitee.qdbp.able.result.ResultCode;
import com.gitee.qdbp.base.model.consts.Keys;
import com.gitee.qdbp.general.common.api.reusable.basic.ISimpleTreeBasic;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeBean;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeCode;
import com.gitee.qdbp.general.common.api.reusable.model.SimpleTreeWhere;
import com.gitee.qdbp.general.common.api.reusable.service.ISimpleTreeQueryer;
import com.gitee.qdbp.tools.codec.CodeTools;
import com.gitee.qdbp.tools.utils.VerifyTools;

/**
 * 基础树形数据业务处理类
 *
 * @author zhh
 * @version 170816
 */
@Service
@Transactional(readOnly = true)
public class SimpleTreeQueryer implements ISimpleTreeQueryer {

    /** 日志对象 **/
    private static final Logger log = LoggerFactory.getLogger(SimpleTreeExecutor.class);

    /** 基础节点DAO **/
    @Autowired
    private ISimpleTreeBasic simpleTreeBasic;

    public static CodeTools tools = new CodeTools(CATEGORY_CODE_LENGTH, CATEGORY_CODE_LENGTH);

    /** 查询节点详情 **/
    @Override
    public SimpleTreeBean find(SimpleTreeCode model) throws ServiceException {
        String scene = model.getSceneType();
        if (VerifyTools.isBlank(scene)) {
            log.error("params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        String nodeCode = model.getNodeCode();
        if (VerifyTools.isBlank(nodeCode)) {
            log.error("params is null: NodeCode");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        SimpleTreeWhere where = new SimpleTreeWhere();
        where.setSceneType(scene);
        where.setNodeCode(nodeCode);
        return simpleTreeBasic.find(where);
    }

    /** 查询节点列表 **/
    @Override
    public PageList<SimpleTreeBean> list(String scene, SimpleTreeWhere where, OrderPaging paging)
            throws ServiceException {
        if (VerifyTools.isBlank(scene)) {
            log.error("params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }

        where.setSceneType(scene);
        return simpleTreeBasic.list(where, paging);
    }

    /** 查询节点列表, parents=是否查询父节点 **/
    @Override
    public List<SimpleTreeBean> list(String scene, List<String> nodeCodes, boolean parents) throws ServiceException {
        Set<String> codes = new HashSet<>();
        if (!parents) {
            codes.addAll(nodeCodes);
        } else {
            for (String nodeCode : nodeCodes) {
                List<String> temp = tools.split(nodeCode, true);
                codes.addAll(temp);
            }
        }
        SimpleTreeWhere w = new SimpleTreeWhere();
        w.setSceneType(scene);
        w.setNodeCodes(new ArrayList<>(codes));
        PageList<SimpleTreeBean> temp = simpleTreeBasic.list(w, OrderPaging.NONE);
        List<SimpleTreeBean> result = new ArrayList<>();
        for (String i : codes) { // 保证顺序
            for (SimpleTreeBean bean : temp) {
                if (i.equals(bean.getNodeCode())) {
                    result.add(bean);
                }
            }
        }
        return result;
    }

    /** 查询父节点列表, self=是否包含自身 **/
    @Override
    public List<SimpleTreeBean> parents(String scene, String nodeCode, boolean self) throws ServiceException {
        if (VerifyTools.isBlank(scene)) {
            log.error("params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        List<SimpleTreeBean> parents = new ArrayList<>();
        if (VerifyTools.isBlank(nodeCode)) {
            return parents;
        }

        List<String> codes = tools.split(nodeCode, self);
        SimpleTreeWhere w = new SimpleTreeWhere();
        w.setSceneType(scene);
        w.setNodeCodes(codes);
        PageList<SimpleTreeBean> temp = simpleTreeBasic.list(w, OrderPaging.NONE);
        for (String i : codes) { // 保证顺序
            for (SimpleTreeBean bean : temp) {
                if (i.equals(bean.getNodeCode())) {
                    parents.add(bean);
                }
            }
        }
        return parents;
    }

    /** 查询子节点列表 **/
    @Override
    public PageList<SimpleTreeBean> children(String scene, String nodeCode, OrderPaging paging) throws ServiceException {
        if (VerifyTools.isBlank(scene)) {
            log.error("params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        String parentCode = nodeCode;
        if (VerifyTools.isBlank(parentCode)) {
            parentCode = Keys.ROOT_CODE;
        }

        SimpleTreeWhere where = new SimpleTreeWhere();
        where.setSceneType(scene);
        where.setParentCode(parentCode);
        return simpleTreeBasic.list(where, paging);
    }

    /** 查询所有后代节点列表 **/
    @Override
    public PageList<SimpleTreeBean> descendants(String scene, String nodeCode, OrderPaging paging) throws ServiceException {
        if (VerifyTools.isBlank(scene)) {
            log.error("params is null: SceneType");
            throw new ServiceException(ResultCode.PARAMETER_IS_REQUIRED);
        }
        String parentCode = nodeCode;
        if (Keys.ROOT_CODE.equals(parentCode)) {
            parentCode = null;
        }

        SimpleTreeWhere where = new SimpleTreeWhere();
        where.setParentCodeStarts(parentCode);
        where.setLevelIndexMin(tools.level(parentCode) + 1); // 不包含parent自身
        return simpleTreeBasic.list(where, paging);
    }

}
